package com.eastfair.venueservice.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperService;
import com.eastfair.builder.dto.ExhibitorDTO;
import com.eastfair.pay.dto.TransactionOrderDTO;
import com.eastfair.pay.enumeration.TransactionOrderOrderStatusEnum;
import com.eastfair.pay.enumeration.TransactionOrderOrderTypeEnum;
import com.eastfair.venueservice.dto.BondManageDTO;
import com.eastfair.venueservice.dto.ExhibitionSettlementDTO;
import com.eastfair.venueservice.entity.BondManage;
import com.eastfair.venueservice.enums.BondManagePayStatusEnum;
import com.eastfair.venueservice.vo.BondManageVO;
import com.eastfair.venueservice.vo.ExhibitionSettlementVO;

import java.math.BigDecimal;
import java.util.List;

/**
 * <p>
 * 业务接口
 * 保证金管理
 * </p>
 *
 * @author lyw
 * @date 2023 -02-14
 */
public interface BondManageService extends SuperService<BondManage> {

    /**
     * 分页查询保证金管理列表
     *
     * @param pageParams the page params
     * @return page
     */
    IPage<BondManageVO> queryBondManageList(PageParams<BondManageDTO> pageParams);

    /**
     * 通过服务商id获取保证金集合
     *
     * @param exhibitorDTO the exhibitor dto
     * @return bond manage list
     */
    List<BondManageVO> getBondManageList(ExhibitorDTO exhibitorDTO);

    /**
     * 获取场馆保证金的结算单
     *
     * @param query the query
     * @return the bond manage settlement by exhibition id
     */
    ExhibitionSettlementVO getVenueBondManageSettlement(ExhibitionSettlementDTO query);

    /**
     * 服务商ID查询保证金列表.
     *
     * @param serviceProviderId the service provider id
     * @return the bond manage list by service provider id
     */
    List<BondManageVO> getBondManageListByServiceProviderId(Long serviceProviderId);

    /**
     * 通过id查询保证金信息
     *
     * @param id the id
     * @return bond manage vo by id
     */
    BondManageVO getBondManageVOById(Long id);

    /**
     * 查询保证金列表.
     *
     * @param bondManageDTO the bond manage dto
     * @return the list
     */
    List<BondManage> listBondManage(BondManageDTO bondManageDTO);

    /**
     * 查询结算保证金
     *
     * @param bondManageDTO the bond manage dto
     * @return the list
     */
    List<BondManage> listBondManageForSettlement(BondManageDTO bondManageDTO);

    /**
     * 服务商ID，展会ID查询场馆保证金
     *
     * @param serviceProviderId  the service provider id
     * @param exhibitionManageId the exhibition manage id
     * @return the list
     */
    List<BondManage> listVenueBondByServiceProviderId(Long serviceProviderId, Long exhibitionManageId);

    /**
     * 订单编号查询保证金订单.
     *
     * @param orderNumber the order number
     * @return the vo by order number
     */
    BondManageVO getVOByOrderNumber(String orderNumber);

    /**
     * 订单编号查询保证金订单.
     *
     * @param orderNumber the order number
     * @return the by order number
     */
    BondManage getByOrderNumber(String orderNumber);

    /**
     * 保存保证金管理
     *
     * @param bondManageDTO the bond manage dto
     * @return bond manage
     */
    BondManage saveBondManageInfo(BondManageDTO bondManageDTO);

    /**
     * 保存场馆保证金.
     *
     * @param bondManageDTO the bond manage dto
     * @return the bond manage
     */
    BondManage saveForVenue(BondManageDTO bondManageDTO);

    /**
     * 设置保证金金额
     *
     * @param bondManageDTO the bond manage dto
     * @return boolean
     */
    Boolean updateBondManageById(BondManageDTO bondManageDTO);

    /**
     * 更新保证金支付金额.
     *
     * @param bondManageDTO the bond manage dto
     * @return the boolean
     */
    BondManage updatePayAmount(BondManageDTO bondManageDTO);

    /**
     * 更新退款状态
     *
     * @param bondManageDTO the service order dto
     * @return the service order
     */
    BondManage updateRefundStatus(BondManageDTO bondManageDTO);

    /**
     * 通过服务商id删除设置保证金信息
     *
     * @param serviceProviderId the service provider id
     * @return boolean
     */
    Boolean delBondManageByServiceProviderId(Long serviceProviderId);

    /**
     * 通过服务商id, 展会ID删除设置保证金信息
     *
     * @param serviceProviderId  the service provider id
     * @param exhibitionManageId the exhibition manage id
     * @return the boolean
     */
    boolean delBondManageByServiceProviderId(Long serviceProviderId, Long exhibitionManageId);

    /**
     * 生成支付系统交易订单.
     *
     * @param bondManageDTO the bond manage dto
     * @return the boolean
     */
    boolean saveTransactionOrder(BondManageDTO bondManageDTO);

    /**
     * 生成支付系统交易订单.
     *
     * @param id the id
     * @return the boolean
     */
    boolean saveTransactionOrder(Long id);

    /**
     * 创建支付系统交易订单
     *
     * @param bondManage the bond manage
     * @return the transaction order dto
     */
    BondManageDTO completeForTransactionOrder(BondManage bondManage);

    /**
     * 是否可扣除保证金
     *
     * @param exhibitionId       the exhibition id
     * @param serviceProviderId  the service provider id
     * @param shouldDeductAmount the should deduct amount
     * @return the boolean
     */
    int canDeductBond(Long exhibitionId, Long serviceProviderId, BigDecimal shouldDeductAmount);

    /**
     * 扣除保证金.
     *
     * @param exhibitionId       the exhibition id
     * @param serviceProviderId  the service provider id
     * @param shouldDeductAmount the should deduct amount
     * @return the boolean
     */
    BondManage deductBondAmount(Long exhibitionId, Long serviceProviderId, BigDecimal shouldDeductAmount);

    /**
     * 扣除保证金
     *
     * @param orderNumber        the order number
     * @param shouldDeductAmount the should deduct amount
     * @return the bond manage
     */
    BondManage deductBondAmount(String orderNumber, BigDecimal shouldDeductAmount);

    /**
     * 扣除保证金
     *
     * @param bondManage         the bond manage
     * @param shouldDeductAmount the should deduct amount
     * @return the bond manage
     */
    BondManage deductBondAmount(BondManage bondManage, BigDecimal shouldDeductAmount);

    /**
     * 退还保证金
     *
     * @param exhibitionId       the exhibition id
     * @param serviceProviderId  the service provider id
     * @param shouldRefundAmount the should deduct amount
     * @return the boolean
     */
    boolean refundBondManage(Long exhibitionId, Long serviceProviderId, BigDecimal shouldRefundAmount);

    /**
     * 退还保证金
     *
     * @param orderNumber        the order number
     * @param shouldRefundAmount the should refund amount
     * @return the boolean
     */
    boolean refundBondManage(String orderNumber, BigDecimal shouldRefundAmount);

    /**
     * 退还保证金.
     *
     * @param bondManage         the bond manage
     * @param shouldRefundAmount the refundable amount
     * @return the boolean
     */
    boolean refundBondManage(BondManage bondManage, BigDecimal shouldRefundAmount);

    /**
     * 发起退款.
     *
     * @param bondManageDTO the bond manage dto
     * @return the boolean
     */
    boolean applyBondManageRefund(BondManageDTO bondManageDTO);

    /**
     * 发起退款申请
     *
     * @param bondManageDTO the bond manage dto
     * @return the boolean
     */
    boolean acceptApplyRefund(BondManageDTO bondManageDTO);

    /**
     * 计算保证金结算单
     *
     * @param bondManageList the bond manage list
     * @return the exhibition settlement vo
     */
    static ExhibitionSettlementVO calculateExhibitionSettlement(List<BondManage> bondManageList){
        ExhibitionSettlementVO exhibitionSettlementVO = new ExhibitionSettlementVO();
        // 保证金已支付金额
        BigDecimal totalPayAmount = BigDecimal.ZERO;
        BigDecimal totalBondAmount = BigDecimal.ZERO;
        for (BondManage bondManage: bondManageList) {
            if (BondManagePayStatusEnum.PAYED.getCode().equals(bondManage.getPayStatus()) || BondManagePayStatusEnum.PARTPAY.getCode().equals(bondManage.getPayStatus())) {
                BigDecimal payAmount = bondManage.getPayAmount() == null ? BigDecimal.ZERO : bondManage.getPayAmount();
                totalPayAmount = totalPayAmount.add(payAmount);
            }
            // 保证金应付金额
            BigDecimal bondAmount = bondManage.getBondAmount() == null ? BigDecimal.ZERO : bondManage.getBondAmount();
            totalBondAmount = totalBondAmount.add(bondAmount);
        }
        exhibitionSettlementVO.setBondAmount(totalPayAmount);
        exhibitionSettlementVO.setPayableBondAmount(totalBondAmount);
        return exhibitionSettlementVO;
    }

    /**
     * 转换为支付订单
     *
     * @param bondManageDTO the bond manage dto
     * @return the transaction order dto
     */
    static TransactionOrderDTO toTransactionOrder(BondManageDTO bondManageDTO) {
        TransactionOrderDTO transactionOrderDTO = new TransactionOrderDTO();
        transactionOrderDTO.setExhibitionId(bondManageDTO.getExhibitionManageId());
        transactionOrderDTO.setExhibitionName(bondManageDTO.getExhibitionManageName());
        transactionOrderDTO.setOrderType(TransactionOrderOrderTypeEnum.BOND);
        transactionOrderDTO.setOrderNum(bondManageDTO.getOrderNumber());
        transactionOrderDTO.setOrderAmount(bondManageDTO.getBondAmount());
        transactionOrderDTO.setOrderTime(bondManageDTO.getCreateTime());
        transactionOrderDTO.setOrderStatus(TransactionOrderOrderStatusEnum.UNPAY);
        transactionOrderDTO.setPayer(bondManageDTO.getServiceProviderName());
        transactionOrderDTO.setPayee(bondManageDTO.getPayee());
        transactionOrderDTO.setSystemCode(bondManageDTO.getSystemScene());
        transactionOrderDTO.setPaymentPeriods(1);
        return transactionOrderDTO;
    }
}
